package xjutils

import (
	"encoding/json"
	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/model"
	"github.com/nacos-group/nacos-sdk-go/vo"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"strings"
)

func NacosRegisterService(appConfig AppConfig) (naming_client.INamingClient, error) {
	sc := []constant.ServerConfig{
		{
			IpAddr: appConfig.Register.Url,
			Port:   appConfig.Register.Port,
		},
	}

	cc := constant.ClientConfig{
		NamespaceId: appConfig.Config.NamespaceId, //namespace id
		TimeoutMs:   5000,
		//ListenInterval:      10000,
		//NotLoadCacheAtStart: true,
		LogDir:   `log`,
		CacheDir: `cache`,
		//RotateTime:          "1h",
		//MaxAge:              3,
		//LogLevel:            "debug",
		LogLevel: "error",
	}

	client, err := clients.CreateNamingClient(map[string]interface{}{
		"serverConfigs": sc,
		"clientConfig":  cc,
	})

	if err != nil {
		panic(err)
	}

	//Register with default cluster and group
	//ClusterName=DEFAULT,GroupName=DEFAULT_GROUP
	param := vo.RegisterInstanceParam{
		Ip:          appConfig.App.Url,
		Port:        appConfig.App.Port,
		ServiceName: appConfig.App.Name,
		Weight:      1,
		Enable:      true,
		Healthy:     true,
		Ephemeral:   true,
		Metadata:    map[string]string{"CTR_VERSION": "mng", "preserved.register.source": "golang"},
	}
	_, err = client.RegisterInstance(param)
	return client, err
}

func NacosGetService(appConfig AppConfig, serviceName string) (string, error) {
	sc := []constant.ServerConfig{
		{
			IpAddr: appConfig.Register.Url,
			Port:   appConfig.Register.Port,
		},
	}

	cc := constant.ClientConfig{
		NamespaceId: appConfig.Config.NamespaceId, //namespace id
		TimeoutMs:   5000,
		//ListenInterval:      10000,
		//NotLoadCacheAtStart: true,
		LogDir:   `log`,
		CacheDir: `cache`,
		//RotateTime:          "1h",
		//MaxAge:              3,
		//LogLevel:            "debug",
		LogLevel: "error",
	}

	client, err := clients.CreateNamingClient(map[string]interface{}{
		"serverConfigs": sc,
		"clientConfig":  cc,
	})

	if err != nil {
		return "", err
	}

	services, err := client.GetService(vo.GetServiceParam{
		ServiceName: serviceName,
		Clusters:    []string{"DEFAULT"},    // default value is DEFAULT
		GroupName:   appConfig.Config.Group, // default value is DEFAULT_GROUP
	})
	if err != nil {
		return "", err
	}
	bb, err := json.Marshal(&services)
	return string(bb), err
}

func NacosSelectInstances(appConfig AppConfig, serviceName, prefix string) (string, error) {
	sc := []constant.ServerConfig{
		{
			IpAddr: appConfig.Register.Url,
			Port:   appConfig.Register.Port,
		},
	}

	cc := constant.ClientConfig{
		NamespaceId: appConfig.Config.NamespaceId, //namespace id
		TimeoutMs:   5000,
		//ListenInterval:      10000,
		//NotLoadCacheAtStart: true,
		LogDir:   `log`,
		CacheDir: `cache`,
		//RotateTime:          "1h",
		//MaxAge:              3,
		//LogLevel:            "debug",
		LogLevel: "error",
	}

	client, err := clients.CreateNamingClient(map[string]interface{}{
		"serverConfigs": sc,
		"clientConfig":  cc,
	})

	if err != nil {
		return "", err
	}

	instances, err := client.SelectInstances(vo.SelectInstancesParam{
		ServiceName: serviceName,
		GroupName:   appConfig.Config.Group, // default value is DEFAULT_GROUP
		Clusters:    []string{"DEFAULT"},    // default value is DEFAULT
		HealthyOnly: true,                   // default value is DEFAULT_GROUP
	})
	if err != nil || instances == nil || len(instances) == 0 {
		return "", err
	}
	strs := make([]string, 0)
	for _, item := range instances {
		strs = append(strs, item.Ip+":"+strconv.FormatUint(item.Port, 10))
	}
	maps := map[string][]string{prefix: strs}
	bb, err := json.Marshal(&maps)
	//订阅
	err2 := client.Subscribe(&vo.SubscribeParam{
		ServiceName: serviceName,
		GroupName:   appConfig.Config.Group, // default value is DEFAULT_GROUP
		Clusters:    []string{"DEFAULT"},    // default value is DEFAULT
		SubscribeCallback: func(services []model.SubscribeService, err error) {
			strs2 := make([]string, 0)
			for _, item := range services {
				strs2 = append(strs2, item.Ip+":"+strconv.FormatUint(item.Port, 10))
			}
			maps2 := map[string][]string{prefix: strs2}
			bb2, _ := json.Marshal(&maps2)
			log.Printf(" callback return services:%s \n", string(bb2))
			httpPost("http://"+appConfig.App.Url+":"+strconv.FormatUint(appConfig.App.Port, 10)+"/servicechange", string(bb2))
		},
	})
	if err2 != nil {
		log.Println(err2)
	}
	return string(bb), err
}

func httpPost(url string, str string) {
	resp, err := http.Post(url,
		"application/x-www-form-urlencoded",
		strings.NewReader(str))
	if err != nil {
		log.Println(err)
	}

	defer resp.Body.Close()
	_, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
	}
	//log.Println(string(body))
}
